<template>
	<view class="content">
		<view class="videobox">
			<!-- 加载ui -->
			<view class="loading" v-show="isLoading">
				<view class="loading_mark">
				</view>
				<view
					style="position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);display: flex;gap: 10rpx;">
					<up-loading-icon textSize="18" color="#fff"></up-loading-icon>
					<text style="font-weight: bold;color: #fff;">加载中...</text>
				</view>
			</view>

			<video id="myVideo" :enableHardwareAcceleration="true" style="position: relative;"
				:src="VIDEO_URL + videosList[videoIndex].url" :controls="false" @timeupdate="onTimeUpdate"
				@loadedmetadata="beforeVideoInit" :show-center-play-btn="false" @click="handleVideoClick"
				:autoplay="false" :enable-progress-gesture="false" @pause="handleVideoPause" @ended="handleVideoEnd"
				@waiting="handleVideoWating" :vslide-gesture-in-fullscreen="false" enable-full-screen
				object-fit="contain">
				<view style="width: 100%;height: 100%;position: relative;" v-if="isFullScreen">
					<!-- 视频内部进度条 -->
					<view class="detailbox" :style="{ 'opacity': showProgress ? '1' : '0' }">
						<text>{{ secondToMinute(videoProcess) }}</text>
						<view class="progressbox">
							<view class="progress" :style="{ width: progress + '%' }"></view>
							<view class="dot" :style="{ 'margin-left': progress + '%' }"></view>
						</view>
						<text>{{ secondToMinute(videoEndTime) }}</text>
						<image @click="handleFullScreen(1)" class="fullScreen"
							style="width: 25rpx;height: 25rpx;margin-left: 40rpx;flex-shrink: 0;"
							src="../../static/icons/fullScreen.png" mode=""></image>
					</view>
					<!-- 视频内部暂停按钮 -->
					<view class="playbth" v-show="!isPlaying">
						<image src="../../static/images/play.png" mode="" @click="handleVideoClick"></image>
					</view>
				</view>
			</video>
			<!-- 进度条 -->
			<view class="detailbox" v-if="!isFullScreen" :style="{ 'opacity': showProgress ? '1' : '0' }">
				<text>{{ secondToMinute(videoProcess) }}</text>
				<view class="progressbox">
					<view class="progress" :style="{ width: progress + '%' }"></view>
					<view class="dot" :style="{ 'margin-left': progress + '%' }"></view>
				</view>
				<text>{{ secondToMinute(videoEndTime) }}</text>
				<image @click="handleFullScreen(0)" class="fullScreen"
					style="width: 50rpx;height: 50rpx;margin-left: 40rpx;flex-shrink: 0;"
					src="../../static/icons/fullScreen.png" mode=""></image>
			</view>
			<view class="statusbox" @click="handlePopClick" v-if="goToSignVisiable">
				<text>{{ hasApplicate ? '已报名' : '去报名' }}</text>
			</view>
			<view class="playbth" v-show="!isPlaying">
				<image src="../../static/images/play.png" mode="" @click="handleVideoClick"></image>
			</view>


		</view>
		<view style="width: 100%; height: 20px; background-color: #f0f0f0;"></view>
		<view class="bottombox">
			<view class="titlebox">
				<text>{{ videoDetail.activityName }}</text>
			</view>
			<view class="item" v-for="(item, index) in videosList" :key="index" @click="handleVideoItemCLick(index)">
				<view class="left">
					<text>{{ item.name }}</text>
					<text>{{ secondToMinute(index === videoIndex ? videoProcess : item.process) + "/" +
						secondToMinute(item.length)}}</text>
				</view>
				<view class="bth">
					<up-button v-if="index === videoIndex && !videoAllEndStatus" :plain="true" type="error" text="学习中"
						：color="#dc2006" :customStyle="{
							color: '#eb2403'
						}"></up-button>
					<up-button v-else-if="index < videoIndex || videoAllEndStatus" type="primary" text="已完成"
						color="#e8e8e8"></up-button>
					<up-button v-else type="primary" text="未完成" color="#e8e8e8"></up-button>
				</view>
			</view>
		</view>
		<up-popup :show="isShowPopup" mode="center" round="20">
			<view class="popup">
				<image src="../../static/images/complete.png" mode=""></image>
				<view class="titlebox">
					<text>线上学习已完成</text>
					<text>请确认是否报名参加线下学习</text>
				</view>
				<view class="bthiamge" @click="gotoSignup">报名参加</view>
			</view>
		</up-popup>
	</view>
</template>

<script setup>
	import {
		reactive,
		ref,
		watch
	} from 'vue';
	import {
		getActivityById,
		updateUserProcess,
		getUserTraining,
		getActivityWatchLength
	} from '../../api/activity.js';
	import {
		onLoad,
		onUnload
	} from '@dcloudio/uni-app'
	import {
		VIDEO_URL
	} from "../../uitls/global.js"
	//创建音频控制器对象
	const videoContext = uni.createVideoContext("myVideo");
	//当前视频播放下标
	let videoIndex = ref(0);
	//当前视频进度
	let videoProcess = ref(0);
	//上个页面传入的参数
	let videoDetail = ref({
		activityName: "加载中"
	});
	//观看的视频进度
	let watchedNum = ref(0);
	//视频播放状态
	let isPlaying = ref(false);
	//当前视频长度
	let videoEndTime = ref("")
	//视频数组
	let videosList = reactive([{
		name: "loading",
		url: 'loading',
		length: "loading",
		process: 0
	}]);
	//进度条
	let progress = ref(0)
	//所有的视频进度
	let videosProgresses = reactive([]);
	//展示报名弹窗
	let isShowPopup = ref(false);
	//展示进度条
	let showProgress = ref(false);
	//可报名的数组
	let applicationList = ref([]);
	//所有视频全部播放完毕状态
	let videoAllEndStatus = ref(false);
	//计时器 用于控制进度条的显示与隐藏
	let timer = null;
	/*
	在真机测试中存在开屏第一个视频未从进度播放而是直接从0播放 
	怀疑原因是跳转的时候因为视频没有加载好导致seek无效 
	因此设置这个flag在视频加载好后跳转
	*/
	let initFlag = true;
	//去学习按钮显示
	let goToSignVisiable = ref(false);
	//视频全屏状态
	let isFullScreen = ref(false);
	//用户是否报名
	let hasApplicate = ref(false);
	//必须看完的时长
	let mustWatchTime = 0;
	//loading显示
	let isLoading = ref(true);
	//绝对进度（秒）
	let absoluteProgress = 0;
	//因为update函数并不是每秒调用一次，要实现计算绝对秒就要做到每秒自增1
	let oldVideoProcess = 0;
	//防抖计时器
	let debounceTimer = null;
	//跟新用户进度
	function updateProcess(index, process) {
		return new Promise(async (resolve, reject) => {
			// 如果定时器已存在，清除它
			if (debounceTimer) {
				clearTimeout(debounceTimer);
			}

			// // 设置新的定时器
			debounceTimer = setTimeout(async () => {
				try {
					const query = {
						activityId: videoDetail.value.activityId,
						currentIndex: index,
						process: process
					};

					const {
						data
					} = await updateUserProcess(query);

					if (!data) {
						reject("上传失败");
					} else {
						resolve(data);
					}

				} catch (error) {
					reject(error);
				}

			}, 300);
		});
	}
	//视频缓冲
	function handleVideoWating() {
		isLoading.value = true;
	}

	//处理视频暂停时间
	async function handleVideoPause(e) {
		isPlaying.value = false;
		await updateProcess(videoIndex.value, videoProcess.value);
	}

	//处理视频播放结束
	async function handleVideoEnd(e) {
		//上传进度
		await updateProcess(videoIndex.value, videosList[videoIndex.value].length);
		//更新页面显示的进度
		videosList[videoIndex.value].process = videoProcess.value;
		//修改完成播放数组的值
		watchedNum.value[videosList.length - 1 - videoIndex.value] = "1";
		//没有播放完那就切换下一个视频
		playController("next")
	}

	//视频控制器
	function playController(mode) {
		if (mode === 'init') {
			videoProcess.value = videosProgresses[videoIndex.value] || 0;
			isLoading.value = true;
			oldVideoProcess = videoProcess.value; //记录上一次的进度
			return;
		} else if (mode === 'next') {
			computedNextVideoIndex();
			if (!videoAllEndStatus.value) {
				videoProcess.value = parseInt(videosProgresses[videoIndex.value]) || 0;
				oldVideoProcess = 0;
				handleVideoClick()
			}
			return;

		}
		//部分视频比较大 初始化加载比较慢 做ui显示
		if (!videoAllEndStatus.value && !videoAllEndStatus.value) {
			isLoading.value = true;
		}
	}

	//视频更新函数
	function onTimeUpdate(e) {
		progress.value = (e.detail.currentTime / e.detail.duration) * 100 //进度条
		//更新视频当前播放的时间
		videoProcess.value = e.detail.currentTime;
		//判断是否看完了必须看完的时间
		canSignup();
	}
	//判断是否第一次播放
	function firstPlay() {
		if (initFlag) {
			initFlag = false;
			videoContext.seek(videoProcess.value);
		}
	}

	//数字TO时间格式
	function secondToMinute(duration) {
		const minutes = String(Math.floor(duration / 60)).padStart(2, '0')
		const seconds = String(Math.floor(duration % 60)).padStart(2, '0')
		return `${minutes}:${seconds}`
	}
	//获取视频长度 ======视频加载好后自动触发
	function beforeVideoInit(e) {
		videoEndTime.value = e.detail.duration;
		firstPlay();
		if (videoAllEndStatus.value) return;
		handleVideoClick();
	}
	//视频点击
	function handleVideoClick() {
		if (videoAllEndStatus.value) {
			uni.showToast({
				icon: 'none',
				title: '您已看完所有视频'
			})
			return;
		}
		showProgress.value = true;
		if (isPlaying.value) {
			isPlaying.value = false;
			videoContext.pause();
			clearTimeout(timer);
			timer = null
		} else {
			isPlaying.value = true;
			videoContext.play();
		}
		if (!timer) {
			timer = setTimeout(() => {
				showProgress.value = false;
			}, 3000)
		}
	}
	//全屏
	function handleFullScreen(type) {
		if (type === 0) {
			//进入全屏
			videoContext.requestFullScreen({
				direction: 90,
			});

			isFullScreen.value = true;
		} else {
			//退出全屏
			videoContext.exitFullScreen();
			isFullScreen.value = false;
		}

	}
	//跳转到报名页面
	function gotoSignup() {
		uni.navigateTo({
			url: "/pages/index/signup?data=" + JSON.stringify(videoDetail.value) + "&applicationData=" + JSON
				.stringify(applicationList.value)
		})
	}

	//去学习
	function handlePopClick() {
		//TODO: 判断是否看时间足够长或者全部看完了
		if (hasApplicate.value) {
			uni.showToast({
				title: "已报名无需重复报名~",
				icon: 'none'
			})
			return;
		}
		const time = videosProgresses.reduce((sum, num) => {
			return sum + num;
		}, 0)
		if (time < mustWatchTime * 60) {
			uni.showToast({
				title: `观看时间不足${mustWatchTime}分钟，请继续观看视频`,
				icon: 'none'
			})
			return;
		}
		isShowPopup.value = true;
	}


	//初始化值
	function initVideoDetail() {
		//没有则初始化数组
		if (!videoDetail.value.videosProcess) {
			videoDetail.value.videosProcess = [];
			for (let i in videosList) {
				videoDetail.value.videosProcess.push(0);
			}
			videoDetail.value.videosProcess = JSON.stringify(videoDetail.value.videosProcess);
		} else {
			//有则需要检查进度数组和视频列表数组长度是否已知
			if (!videosList.length === videoDetail.value.videosProcess.length) {
				// uni.showToast({
				// 	title: "视频记录出错，请联系管理员"
				// })
			}
		}
		if (!videoDetail.value.videosStatus) {
			videoDetail.value.videosStatus = 0;
		}
	}

	//判断该活动是否还能报名培训
	async function canApplicate() {
		if (videoDetail.value.trainingInfo != "" || videoDetail.value.trainingInfo != null) {
			const dates = JSON.parse(videoDetail.value.trainingInfo)
			dates.map(item => {
				applicationList.value.push(item.date)
			})
			if (applicationList.value.length > 0) {
				goToSignVisiable.value = true;
			}
		}

		// if (!Array.isArray(JSON.parse(videoDetail.value.trainingInfo))) {
		// 	return;
		// }
		// try {
		// 	const dates = JSON.parse(videoDetail.value.trainingInfo).map((el) => {
		// 		return {
		// 			/**
		// 			 *  2025/3/14 日期格式："date":"2025-03-22 14:04:00,20:00:00"
		// 			 */
		// 			startDate: el.startDate,
		// 			endDate: el.endDate
		// 		}
		// 		// return el.date.split(",")[0];
		// 	})
		// 	if (applicationList.value.length > 0) {
		// 		goToSignVisiable.value = true;
		// 	}
		// 	console.log(applicationList.value);
		// } catch (e) {
		// 	return;
		// }
	}
	//比较时间
	// function compareTime(dates) {

		// const givenTimestamp = Date.now();
		// return arrs.filter(item => {
		// 	const startTimestamp = new Date(item.startDate.replace(/-/g, '/')).getTime();
		// 	return startTimestamp > givenTimestamp;
		// }).map(item => item.date);
	// }
	//判断是否看完了必须看完的时间
	async function canSignup() {
		if (absoluteProgress === 0) {
			//计算视频进度数组求出当前进度
			absoluteProgress = videosProgresses.reduce((sum, num) => {
				return sum + num;
			}, 0)
		}
		const timeDiff = videoProcess.value - oldVideoProcess
		if (timeDiff > 1) {
			absoluteProgress += 1;
			oldVideoProcess = videoProcess.value;
		} else if (timeDiff > 0.5) {
			//进度变化则说明缓存完毕
			isLoading.value = false;
		}
		//到达最低观看时间弹出弹窗
		if (absoluteProgress >= mustWatchTime * 60 && mustWatchTime != 0) {
			if (!hasApplicate.value) {
				isShowPopup.value = true;
			}
			//暂停视频
			handleVideoPause();
		}
	}
	//更新下一个视频的下标
	function computedNextVideoIndex() {
		let flag = true;
		//补全位数
		for (let i in videosList) {
			if (watchedNum.value.length < videosList.length) {
				watchedNum.value.unshift("0")
			} else {
				break;
			}
		} //0101 
		let size = watchedNum.value.length - 1;
		for (let i = size; i >= 0; i--) {
			if (watchedNum.value[i] === '0') {
				videoIndex.value = size - i;
				flag = false;
				break;
			}
		}
		if (flag) {
			//看完了
			handleVideoPause();
			//由于视频seek函数哪怕跳转到了最后一秒依然会播放，因此要判断这里是不是已经看完了来更新按钮的状态
			videoAllEndStatus.value = true;
			uni.showToast({
				title: "视频已全部播放完毕。"
			})
			if (!hasApplicate.value) {
				//打开培训报名弹窗
				if (!hasApplicate.value && !isShowPopup.vlaue) {
					isShowPopup.value = true;
				}
			}
		}
	}
	//返回等其他方式关闭页面
	onUnload(async () => {
		await updateProcess(videoIndex.value, videoProcess.value);
		timer = null;
		debounceTimer = null;
	})

	//接受主页参数
	onLoad(async (options) => {
		const activityId = options.item;
		//获取用户报名状态
		const {
			data: signData
		} = await getUserTraining({
			activityId: activityId
		});
		if (signData) {
			//有数据说明已经报名
			hasApplicate.value = true;
		}
		const {
			data
		} = await getActivityById({
			activityId: activityId
		})
		videoDetail.value = data;
		videoDetail.value.activityId = activityId;
		videosList = JSON.parse(videoDetail.value.videosInfo);
		//值要初始化
		initVideoDetail();
		watchedNum.value = (videoDetail.value.videosStatus).toString(2).split('');

		computedNextVideoIndex(); //videoIndex 已赋值

		videosProgresses = JSON.parse(videoDetail.value.videosProcess);
		videosList.forEach((item, index) => {
			item.process = videosProgresses[index];
		})
		//自动播放
		// if (!videoAllEndStatus.value) {
		playController("init"); //没看完自动播放
		// }
		//获取当前视频必看时长
		const {
			data: time
		} = await getActivityWatchLength();
		mustWatchTime = time.minuteNumber;
		//是否还能报名
		canApplicate();
	})
</script>
<style lang="scss" scoped>
	.content {
		display: flex;
		flex-direction: column;
		height: 100vh;
		position: relative;
	}

	.videobox {
		width: 100%;
		position: relative;

		video {
			width: 100%;
		}

		.detailbox {
			width: 100%;
			position: absolute;
			bottom: 10px;
			display: flex;
			justify-content: space-between;
			gap: 5px;
			padding: 0px 10px;
			align-items: center;
			box-sizing: border-box;
			color: white;
			font-size: 12px;
			transition: all 0.3s;

			.progressbox {
				display: flex;
				background-color: white;
				align-items: center;
				position: relative;
				width: 100%;
				height: 4px;

				.progress {
					height: 4px;
					background-color: #FF872E;
					position: absolute;
				}

				.dot {
					width: 15px;
					height: 15px;
					border-radius: 50%;
					background-color: #FF872E;
				}
			}
		}

		.statusbox {
			position: absolute;
			padding: 10px;
			font-size: 12px;
			color: white;
			border-radius: 30px;
			background-color: #d5d5d5;
			width: max-content;
			right: 10px;
			top: 10px;
		}

		.playbth {
			position: absolute;
			top: 50%;
			left: 50%;
			transform: translate(-50%, -50%);
			width: 60px;
			height: 60px;
			z-index: 2;

			image {
				width: 100%;
				height: 100%;
			}
		}
	}

	.bottombox {
		margin-top: 10px;
		border-radius: 10px 10px 0 0;
		background-color: white;
		padding: 10px;
		flex: 1;
		margin-top: -10px;

		.titlebox {
			font-size: 16px;
			font-weight: bold;
			border-bottom: #cacaca solid 1px;
			padding-bottom: 10px;
			margin-bottom: 10px;
		}

		.item {
			display: flex;
			justify-content: space-between;
			align-items: center;
			border-bottom: #cacaca solid 1px;
			padding-bottom: 10px;
			margin-bottom: 10px;

			.left {
				display: flex;
				flex-direction: column;
				gap: 10px;

				text:nth-child(1) {
					font-size: 16px;
					font-weight: bold;
				}

				text:nth-child(2) {
					font-size: 14px;
					color: gray;
				}
			}

			.bth {
				width: 80px;
				height: 30px;

				button {
					height: 100% !important;
				}
			}

			.notStudy button {
				color: gray !important;
			}

		}
	}

	.popup {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: space-between;
		height: 300px;
		width: 300px;
		padding: 20rpx;
		box-sizing: border-box;
		position: relative;

		image:nth-child(1) {
			width: 150px;
			height: 100px;
			position: absolute;
			left: 50%;
			top: -50px;
			transform: translateX(-50%);
		}

		.bthiamge {
			width: 230px;
			height: 60px;
			background-color: #ea2204;
			border-radius: 30px;
			text-align: center;
			line-height: 60px;
			letter-spacing: 5px;
			color: white;
			font-size: 1.2rem;
			font-weight: bold;
		}

		.titlebox {
			display: flex;
			flex-direction: column;
			align-items: center;
			margin-top: 80px;
			gap: 20px;

			text:nth-child(1) {
				font-size: 20px;
				font-weight: bold;
			}

			text:nth-child(2) {
				font-size: 18px;
				color: gray;
			}
		}
	}

	.loading {
		width: 100%;
		height: 100%;
		position: absolute;
		z-index: 9999;
	}

	.loading_mark {
		height: 100%;
		width: 100%;
		display: flex;
		justify-content: center;
		background-color: gray;
		opacity: 0.5;
		align-items: center;
	}
</style>